#ifndef	_J_DOGADJAJI_H_
#define	_J_DOGADJAJI_H_

#include <dogadjaji.h>

//javno  >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

//ZASTAVICE SU DEFINIRANE U sucelje/dogadjaji.h GDJE JE I OPIS RADA!

//stvori novi red dogadjaja
int j_stvori_red_dogadjaja (void *param);

//brise red dogadjaja identificiran sa id-jem koji je jedini parametar
int j_obrisi_red_dogadjaja (void *param);

//dretva se prijavljuje na red dogadjaja:
//globalni ili lokalni (kada je id RED_DOG_DRETVE)
int j_prijavi_se_na_red_dogadjaja (void *param);

//dretva stvara dogadjaj i salje ga ili u neki globalni red ili izravno dretvi
int j_postavi_dogadjaj (void *param);

//procitaj dogadjaj iz reda
int j_dohvati_dogadjaj (void *param);

//kada zavrsi obrada poziva se ova jezgrina funkcija (iz j_obrada_dogadjaja)
//ne pozivati ovu funkciju drukcije!
int j_kraj_obrade_dogadjaja (void *param);

//javno  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<


//dretva ima element za red dogadjaja u opisniku, pa joj samo treba velicina te
//strukture (ostalo nije ni potrebno pa je skriveno)
#if defined(_J_DRETVE_C_) || defined(_J_RED_C_) ||	\
	defined(_J_SINKRONIZACIJA_C_) || defined(_J_PROCESI_C_)

typedef struct {
	struct { void *prvi; void *zadnji; } red_dog;
	void (*funkcija) (void *dogadjaj, void *param);
	void *param;
	int red;
} j_red_dog_dretve_t;

//inicijalizacija u opisniku dretve
void j_dog_inic_podatke_dretve(j_red_dog_dretve_t *red);

#endif	// ostali 

#if defined(_J_DOGADJAJI_C_)

//okvir u kojem se 'dogadjaj_t' nalazi u jezgri - dodani su podaci potrebni za
//upravljanje dogadjajima iz jezgre
typedef struct _j_dogadjaj_t_ {
	dogadjaj_t dog; //mora ostati na pocetku!
	//'korisni' podaci o dogadjaju
	
	void *povratak;
	//za pohranu kazaljke stoga prije dodavanja novog stoga za skok u
	//obradu dogadjaja (ako dogadjaj izazove takvu obradu - ima veci
	//prioritet od dretve

	struct _j_prijava_dog_t_ *prijava;
	//dodatni podaci za obradu (funkcija i parametar), ako je != NULL

	struct _j_dogadjaj_t_ *iduci;
	//za ostvarenje liste dogadjaja
} j_dogadjaj_t;

//"red" dogadjaja, slozenih po prioritetu
typedef struct _j_lista_dogadjaja_t_ {
	j_dogadjaj_t *prvi;
	j_dogadjaj_t *zadnji;
} j_lista_dogadjaja_t;

//dretve se mogu prijaviti na "globalne" redove dogadjaja
//iduca struktura definira podatke o svakoj prijavi
typedef struct _j_prijava_dog_t_ {
	int id_dretve;
	//kojoj dretvi pripada ova prijava - kojoj se proslijedjuje dogadjaj
	
	void (*funkcija) (dogadjaj_t *dogadjaj, void *param);
	//koja se funkcija zove, ako je zadano - parametri su sam dogadjaj i
	//ispod navedeni parametar - ako je funkcija == NULL ne poziva se
	void *param;
	
	struct _j_prijava_dog_t_ *iduci;
} j_prijava_dog_t;

//svaki globalni red moze imati vise prijavljenih dretvi
//prijave su slozene po prioritetu
typedef struct _j_lista_prijava_t_ {
	j_prijava_dog_t *prvi;
	j_prijava_dog_t *zadnji;
} j_lista_prijava_t;

//podaci za globalne redove dogadjaja
//dretve se mogu na njega registrirati i/ili uzimati dogadjaje iz "reda"
typedef struct _j_red_dogadjaja_t_ {
	int id;
	//id reda dogadjaja (nije za sada potreban: id = redni broj)

	int zast;
	//razne zastavice koje definiraju upravljanje redom
	
	int prio;
	//prioritet dogadjaja - ako je u prioritet dogadjaja postavljen ali
	//ima manja vrijednost od ove, onda mu se on poveca stavljanjem u red
	//prioritet ne smije biti manji od 1! (ne moze biti 0)
	
	j_lista_prijava_t prijave;
	//lista prijavljenih dretvi
	
	j_lista_dogadjaja_t red_dog;
	//pohranjeni dogadjaji

	int red;
	//id reda u kojem dretve cekaju na dogadjaj
} j_red_dogadjaja_t;

//red dogadjaja inicijalno pridjeljen dretvi (sadrzan u opisniku dretve)
typedef struct _j_red_dog_dretve_ {
	j_lista_dogadjaja_t red_dog;
	//pohranjeni dogadjaji

	void (*funkcija) (dogadjaj_t *dogadjaj, void *param);
	//koja se funkcija zove, ako je zadano - parametri su sam dogadjaj i
	//ispod navedeni parametar - ako je funkcija == NULL ne poziva se
	void *param;
	
	int red;
	//id reda u kojem dretva ceka na dogadjaj

} j_red_dog_dretve_t;

//pomocne funkcije (deklaracija)
static bool j_stavi_dogadjaj_dretvi (void *dretva, j_dogadjaj_t *dog, int red);
j_dogadjaj_t *j_kopiraj_dogadjaj (j_dogadjaj_t *dog);


//za rad sa sortiranim listama definirana su dva makroa:

//prvi za usporedbu prioriteta dogadjaja (elementi su j_dogadjaj_t *)
//za liste dogadjaja
#define DOG_USPOREDI_PRIO(a, b)	((a->dog.prio) - (b->dog.prio))

//drugi za usporedbu prioriteta dretvi (elementi su j_prijava_dog_t *)
//za liste prijava
#define DOG_USPOREDI_DRETVE(a, b)	\
	(j_opdr_prio(j_dohvati_opisnik(a->id_dretve)) -	\
	 j_opdr_prio(j_dohvati_opisnik(b->id_dretve)))

#endif	/* _J_DOGADJAJI_C_ */

#endif	/* _J_DOGADJAJI_H_ */